using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Rocuna.GameEngine.Constants;
using Rocuna.GameEngine.State;
using Rocuna.Graphics;
using Rocuna.HID;

namespace Rocuna.GameEngine
{
    /// <summary>
    /// Game derived class to hold Rocuna specific Game.
    /// Your Game instance should inhert this class to use in the Rocuna engine.
    /// </summary>
    public class RocunaGame : Game
    {
        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="RocunaGame"/> class.
        /// </summary>
        public RocunaGame()
        {
            Graphic = new GraphicsDeviceManager(this);
            Graphic.SupportedOrientations = DisplayOrientation.LandscapeLeft;
        }

        #endregion

        #region Private fields

        private bool _loadingStarted = false;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the graphic device manager.
        /// </summary>
        /// <value>
        /// The graphic device manager.
        /// </value>
        public GraphicsDeviceManager Graphic { get; set; }

        /// <summary>
        /// Gets or sets the sprite batch.
        /// </summary>
        /// <value>
        /// The sprite batch.
        /// </value>
        protected SpriteBatch SpriteBatch { get; set; }

        #endregion

        #region Override methods

        /// <summary>
        /// Called after the Game and GraphicsDevice are created, but before LoadContent.  Reference page contains code sample.
        /// </summary>
        protected override void Initialize()
        {

            SpriteBatch = new SpriteBatch(GraphicsDevice);
            Services.AddService(typeof(SpriteBatch), SpriteBatch);
            base.Initialize();
        }

        /// <summary>
        /// Loading the Game content. should not be used by inherted classes becuse it delayed the splashes screen.
        /// </summary>
        protected sealed override void LoadContent()
        {
            base.LoadContent();
        }

        /// <summary>
        /// Reference page contains links to related conceptual articles.
        /// </summary>
        /// <param name="gameTime">Time passed since the last call to Update.</param>
        protected override void Update(GameTime gameTime)
        {
            if (!_loadingStarted)
                LoadGameContent(gameTime);
            //Polling input from the engine.

            base.Update(gameTime);
        }

        /// <summary>
        /// Reference page contains code sample.
        /// </summary>
        /// <param name="gameTime">Time passed since the last call to Draw.</param>
        protected override void Draw(GameTime gameTime)
        {
            ScreenManager.CurrentScreen.Draw(gameTime);
            base.Draw(gameTime);
        }

        #endregion

        #region Protected Helpers

        /// <summary>
        /// Loads the content of the game.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        protected virtual void LoadGameContent(GameTime gameTime)
        {
            _loadingStarted = true;
            ForceDraw(gameTime);
            GraphicManager.LoadContent();
        }

        /// <summary>
        /// Forces the draw.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        public virtual void ForceDraw(GameTime gameTime)
        {
            BeginDraw();
            Draw(gameTime);
            EndDraw();
        }

        #endregion

        #region Engine Properties

        protected GraphicManager GraphicManager { get; set; }

        protected InputManager InputManager { get; set; }

        protected ScreenManager ScreenManager { get; set; }

        #region Configure Engine

        internal void SetGraphicManager(GraphicManager graphicManager)
        {
            GraphicManager = graphicManager;
            Services.AddService(typeof(GraphicManager), GraphicManager);
        }

        internal void SetInputManager(InputManager inputManager)
        {
            InputManager = inputManager;
            Services.AddService(typeof(InputManager), InputManager);
        }

        internal void SetScreenManager(ScreenManager screenManager)
        {
            ScreenManager = screenManager;
            Services.AddService(typeof(ScreenManager), ScreenManager);
        }

        #endregion

        #endregion
    }
}